iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
自我挑戰組

30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記系列 第 23

保險理賠模擬器:免賠額、共付比、理賠上限怎麼影響保費?

  • 分享至 

  • xImage
  •  

今天要達成什麼

  • 用隨機模擬(不連網、只用標準函式庫)產生「出險頻率」與「事故金額」。
  • 套用三個常見條款:免賠額(deductible)、共付比(coinsurance)、理賠上限(limit)。
  • 算出年度總理賠與純保費(每張保單的期望理賠),並示範改參數的影響。

教育示範用,非商品精算;真實商品需大量資料、監管與精算檢核。

Python 小實作

import random, math, csv

random.seed(42)  # 讓結果可重現(教學用)

# ---- 模型參數(你可以改這裡)----
N_POLICY      = 1000        # 模擬保戶數
LAMBDA_CLAIM  = 0.30        # 每保戶每年的「平均事故件數」(Poisson λ)
DEDUCTIBLE    = 5_000       # 免賠額(每次事故,先自付這麼多)
COINSURANCE   = 0.10        # 共付比(自付比例 10% → 保險公司理賠 90%)
LIMIT_PER_CLAIM = 200_000   # 單次事故理賠上限
EXPENSE_LOADING = 0.20      # 營運/通路加成(示意 20%)

# 事故金額分布(用三角分布,直覺易懂且不需外部套件)
#   low=8,000,高=300,000,最可能值(mode)=60,000(單位:TWD)
def sample_severity():
    return random.triangular(8_000, 300_000, 60_000)

# Knuth 演算法取樣 Poisson(λ)(標準庫無現成函式)
def sample_poisson(lmbda: float) -> int:
    L = math.exp(-lmbda)
    k, p = 0, 1.0
    while p > L:
        k += 1
        p *= random.random()
    return k - 1

def simulate_once(
    n_policy=N_POLICY, lam=LAMBDA_CLAIM,
    deductible=DEDUCTIBLE, coins=COINSURANCE, limit=LIMIT_PER_CLAIM
):
    total_gross = 0.0      # 事故原始金額總和
    total_payout = 0.0     # 保險公司實際支付
    total_claims = 0
    claimants = set()
    rows = []

    for pid in range(1, n_policy + 1):
        n_claims = sample_poisson(lam)
        if n_claims > 0:
            claimants.add(pid)
        for j in range(n_claims):
            gross = sample_severity()
            covered = max(gross - deductible, 0.0)       # 扣免賠額後可理賠部分
            payout = min(covered * (1 - coins), limit)   # 扣共付比+上限
            total_gross += gross
            total_payout += payout
            total_claims += 1
            rows.append({
                "policy_id": pid,
                "claim_no": j + 1,
                "gross": round(gross, 2),
                "payout": round(payout, 2)
            })

    pure_premium = total_payout / n_policy if n_policy else 0.0
    suggested_premium = pure_premium * (1 + EXPENSE_LOADING)

    summary = {
        "保戶數": n_policy,
        "事故件數": total_claims,
        "出險率_件/保單": round(total_claims / n_policy, 3),
        "至少出險一次的保戶占比": round(len(claimants) / n_policy, 3),
        "總事故金額_TWD": round(total_gross, 2),
        "總理賠金額_TWD": round(total_payout, 2),
        "純保費_每張保單_TWD": round(pure_premium, 2),
        "建議保費(含20%加成)_TWD": round(suggested_premium, 2),
        "條款": {
            "免賠額": deductible,
            "共付比": coins,
            "每次理賠上限": limit
        }
    }
    return summary, rows

# ---- 進行一次模擬並輸出結果 ----
summary, rows = simulate_once()
print("=== 模擬結果(方案A)===")
for k, v in summary.items():
    if k != "條款":
        print(f"{k}: {v}")
print("條款:", summary["條款"])

# 可選:存檔,之後拿去做圖或做報表
with open("claims_sim.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=["policy_id","claim_no","gross","payout"])
    writer.writeheader()
    writer.writerows(rows)
print("\n已輸出明細:claims_sim.csv")

# ---- What-if:調高免賠額到 10,000 再跑一次(比較保費變化)----
summary_B, _ = simulate_once(deductible=10_000)
print("\n=== 模擬結果(方案B:免賠額 10,000)===")
for k, v in summary_B.items():
    if k != "條款":
        print(f"{k}: {v}")
print("條款:", summary_B["條款"])

會看到什麼

  • 方案A(免賠額 5,000) 的總理賠與「純保費/每張保單」。
  • 方案B(免賠額 10,000) 的比較結果 —— 通常純保費會明顯下降(因為小額理賠被免賠吸收)。
  • 一份 claims_sim.csv,可以後續拿去畫圖或匯入 Excel。

怎麼解讀?

  • 免賠額越高 → 小額索賠由保戶自付 → 保險公司支出下降 → 純保費下降。
  • 共付比越高(例如 20%)→ 每次事故你要付更多 → 保費可更低。
  • 理賠上限越低 → 超大額事故被封頂 → 保費也會降低,但保障縮水。
    這些就是產品設計的三大槓桿。你可以調參數、重跑幾次(隨機性會有小差異),直覺感受保費與條款的取捨。

延伸練習

  1. 換分布:把 sample_severity() 改成「重尾」更強的分布(例如以 random.lognormvariate(mu, sigma) 模擬嚴重事故)。
  2. 加總上限:把「年度總理賠上限(per policy)」也納入,看看高頻小額的影響。
  3. 可視化:用 matplotlib 畫一張「事故金額 vs 實際理賠」的散點圖。
  4. 保費敏感度:在一個 for 迴圈內遍歷多個免賠額,印出對應純保費,做成一張對照表。

上一篇
用 Python 計算等額本息每月應繳與攤還表
下一篇
健康保險 × 風險因子:用 BMI 做保費等級模擬
系列文
30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言